/*
 * @Copyright: Citylife 2021
  * @Author: shaokui.gu
 * @Date: 2021-02-19 15:28:09
 * @Description: 
 */
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_scaffold_plugin/components/button.dart';
import 'package:flutter_scaffold_plugin/components/gesture_avoid_detector.dart';
import 'package:flutter_scaffold_plugin/components/navigation_bar.dart';
import 'package:flutter_scaffold_plugin/generated/model/connection_info.dart';
import 'package:flutter_scaffold_plugin/generated/model/room_info.dart';
import 'package:flutter_scaffold_plugin/pages/vidu/peers_manager.dart';
import 'package:flutter_scaffold_plugin/pages/vidu/websocket_listener.dart';
import 'package:flutter_scaffold_plugin/utils/dialog/dialog_info.dart';
import 'package:flutter_scaffold_plugin/utils/dialog/dialog_manager.dart';
import 'package:flutter_scaffold_plugin/utils/toast/toast_manager.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart' as WebRTC;
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:core';
import 'dart:io';
import '../../base/base.dart';
import '../../base/base_page.dart';
import '../../utils/locale/local_manager.dart';

class TeacherLivingController extends TemplateController {
  WebRTC.MediaStream _localStream;
  WebRTC.MediaStream _displayStream;

  PeersManager peersManager = PeersManager();
  WebSocketListener socket;
  WebRTC.RTCPeerConnection get peerConnection => this.peersManager.localPeer;

  final _localRenderer = WebRTC.RTCVideoRenderer();
  final _remoteRenderer = WebRTC.RTCVideoRenderer();

  get remoteRenderer => _remoteRenderer;
  get localRenderer => _localRenderer;

  final _hasIntilized = false.obs;
  get hasIntilized => this._hasIntilized.value;
  set hasIntilized(value) => this._hasIntilized.value = value;

  final _isTorchOn = false.obs;
  get isTorchOn => this._isTorchOn.value;
  set isTorchOn(value) => this._isTorchOn.value = value;

  final _isMute = false.obs;
  get isMute => this._isMute.value;
  set isMute(value) => this._isMute.value = value;

  final _isPushing = false.obs;
  get isPushing => this._isPushing.value;
  set isPushing(value) => this._isPushing.value = value;

  final _isRecording = false.obs;
  get isRecording => this._isRecording.value;
  set isRecording(value) => this._isRecording.value = value;

  RoomInfo roomInfo;
  ConnectionInfo connectionInfo;
  final customSessionId = "testSession001";

  WebRTC.MediaRecorder mediaRecorder;
  bool get _isRec => mediaRecorder != null;
  List<WebRTC.MediaDeviceInfo> mediaDevicesList;
  RTCRtpSender displayTrackSender;

  String imageUrl =
      "https://pics0.baidu.com/feed/b17eca8065380cd7b5b4b368e0164d3158828160.jpeg?token=2b92b8e834e0adb890779c4ee3fc412a&s=BD80EB152993C2DC4E3C50D70100C0A2";

  @override
  void onInit() {
    super.onInit();
    _initRenderers();
  }

  _initRenderers() async {
    await _localRenderer.initialize();
    await peersManager.start();
    await _makeCameraCall();
    this.hasIntilized = true;
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  _makeCameraCall() async {
    final mediaConstraints = <String, dynamic>{
      'audio': true,
      'video': {
        'mandatory': {
          'minWidth':
              '1280', // Provide your own width, height and frame rate here
          'minHeight': '720',
          'minFrameRate': '30',
        },
        'facingMode': 'user',
        'optional': [],
      }
    };
    try {
      _localStream =
          await WebRTC.navigator.mediaDevices.getUserMedia(mediaConstraints);
      mediaDevicesList = await WebRTC.navigator.mediaDevices.enumerateDevices();
      _localRenderer.srcObject = _localStream;
      _localStream.getTracks().forEach((element) {
        this.peerConnection.addTrack(element, _localStream);
      });
    } catch (e) {}
    _localRenderer.srcObject = _localStream;
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  _makeDisplayCall() async {
    // final displayConstraints = <String, dynamic>{'audio': true, 'video': true};
    // try {
    // _displayStream = await WebRTC.navigator.mediaDevices
    //     .getDisplayMedia(displayConstraints);
    // _localRenderer.srcObject = _displayStream;
    // final displayTrack = _displayStream.getVideoTracks()[0];
    // this.displayTrackSender =
    // await _peerConnection.addTrack(displayTrack, _displayStream);
    // } catch (e) {}
  }

  createRoom() async {
    final response = await NetworkUtil.instance.sendRequest(
        'openvidu/api/sessions',
        method: NetworkRequestMethd.Post,
        parameters: {
          "customSessionId": customSessionId,
        });
    this.roomInfo = RoomInfo.fromJson(response);
    this.createConnection(customSessionId);
  }

  createConnection(String sessionId) async {
    final response = await NetworkUtil.instance.sendRequest(
        'openvidu/api/sessions/$sessionId/connection',
        method: NetworkRequestMethd.Post,
        parameters: {
          "customSessionId": customSessionId,
        });
    connectionInfo = ConnectionInfo.fromJson(response);
    this.createSocket(connectionInfo.token);
  }

  createSocket(String token) {
    this.socket = WebSocketListener(
      url: "https://192.168.50.116:4443/openvidu",
      sessionName: "flutter 1",
      participantName: "flutter user",
      peersManager: this.peersManager,
      token: token,
    );
    this.peersManager.webSocketListener = this.socket;
  }

  startPushStream() {
    this.isPushing = true;
  }

  stopPushStream() {
    this.isPushing = false;
  }

  void _hangUp() async {
    try {
      await _localStream?.dispose();
      _localRenderer.srcObject = null;
    } catch (e) {
      print(e.toString());
    }
  }

  void startRecording() async {
    if (_localStream == null) throw Exception('Stream is not initialized');
    if (Platform.isIOS) {
      print('Recording is not available on iOS');
      ToastManager.showToast(msg: "iOS 不支持录制");
      return;
    }
    // TODO(rostopira): request write storage permission
    final storagePath = await getExternalStorageDirectory();
    if (storagePath == null) throw Exception('Can\'t find storagePath');

    final filePath = storagePath.path + '/webrtc_sample/test.mp4';
    mediaRecorder = WebRTC.MediaRecorder();
    final videoTrack = _localStream
        .getVideoTracks()
        .firstWhere((track) => track.kind == 'video');
    await mediaRecorder.start(
      filePath,
      videoTrack: videoTrack,
    );
    this.isRecording = true;
  }

  void stopRecording() async {
    await mediaRecorder?.stop();
    this.isRecording = false;
    _hangUp();
    _initRenderers();
  }

  /// 手电筒
  void _toggleTorch() async {
    if (_localStream == null) throw Exception('Stream is not initialized');
    final videoTrack = _localStream
        .getVideoTracks()
        .firstWhere((track) => track.kind == 'video');
    final has = await videoTrack.hasTorch();
    if (has) {
      print('[TORCH] Current camera supports torch mode');
      isTorchOn = !isTorchOn;
      await videoTrack.setTorch(isTorchOn);
      print('[TORCH] Torch state is now ${isTorchOn ? 'on' : 'off'}');
    } else {
      print('[TORCH] Current camera does not support torch mode');
    }
  }

  void toggleCamera() async {
    if (_localStream == null) throw Exception('Stream is not initialized');
    final videoTrack = _localStream
        .getVideoTracks()
        .firstWhere((track) => track.kind == 'video');
    await Helper.switchCamera(videoTrack);
  }

  void toggleVolumeMute() {
    if (_localStream == null) throw Exception('Stream is not initialized');
    final audioTrack = _localStream.getAudioTracks()[0];
    bool mute = !this.isMute;
    // audioTrack.setMicrophoneMute(mute);
    audioTrack.setTorch(mute);
    isMute = mute;
  }

  void _captureFrame() async {
    if (_localStream == null) throw Exception('Stream is not initialized');
    final videoTrack = _localStream
        .getVideoTracks()
        .firstWhere((track) => track.kind == 'video');
    final frame = await videoTrack.captureFrame();
    DialogManager.instance.addDialog(DialogInfo(dialogWidget: () {
      return AlertDialog(
        content: Image.memory(frame.asUint8List(), height: 720, width: 1280),
        actions: <Widget>[
          TextButton(
            onPressed: () {
              Get.back();
            },
            child: Text('OK'),
          )
        ],
      );
    }));
  }

  @override
  onClose() {
    super.onClose();
    if (hasIntilized) {
      _hangUp();
    }
    _localRenderer.dispose();
  }
}

class TeacherLivingPage extends TemplatePage<TeacherLivingController> {
  TeacherLivingPage() : super(title: appString.zhuye);

  @override
  Widget buildBody(BuildContext context) {
    return Stack(
      children: [
        Obx(() => Container(
              child: !this.controller.hasIntilized
                  ? Container()
                  : Container(
                      margin: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
                      width: MediaQuery.of(context).size.width,
                      height: MediaQuery.of(context).size.height,
                      decoration: BoxDecoration(color: Colors.black),
                      child: RTCVideoView(this.controller.localRenderer,
                          objectFit: WebRTC
                              .RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
                          mirror: true),
                    ),
            )),
        Align(
          alignment: Alignment.topLeft,
          child: SafeArea(
            bottom: false,
            child: GestureAvoidDetector(
              onTap: () {
                this.controller._makeDisplayCall();
                Get.toNamed("/expain").then((value) {
                  // this.controller._makeCameraCall();
                });
              },
              child: Container(
                margin: EdgeInsets.only(top: 48),
                constraints: BoxConstraints(
                  maxHeight: 160,
                  maxWidth: 120,
                ),
                child: Hero(
                  tag: "expain_image",
                  child: CachedNetworkImage(imageUrl: this.controller.imageUrl),
                ),
              ),
            ),
          ),
        ),
        Align(
          alignment: Alignment.topCenter,
          child: GestureAvoidDetector(
            onTap: () {},
            child: Container(
              child: NavigationBar.customBar(
                  title: "教师",
                  foregroundColor: Colors.white,
                  backgroundColor: Color.fromARGB(80, 0, 0, 0)),
            ),
          ),
        ),
        Align(
          alignment: Alignment.topRight,
          child: SafeArea(
            bottom: false,
            child: CLTextButton(
              title: "创建房间",
              padding: EdgeInsets.symmetric(horizontal: 15, vertical: 5),
              onPressed: () {
                this.controller.createRoom();
              },
            ),
          ),
        ),
        Align(
          alignment: Alignment.bottomCenter,
          child: Container(
            color: Colors.black,
            height: 70,
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Expanded(
                  flex: 1,
                  child: Obx(
                    () => GestureAvoidDetector(
                      onTap: () {
                        this.controller.toggleVolumeMute();
                      },
                      child: Container(
                        height: 44,
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Icon(
                              this.controller.isMute
                                  ? CupertinoIcons.volume_mute
                                  : CupertinoIcons.volume_up,
                              color: Colors.white,
                            ),
                            Text(
                              this.controller.isMute ? "开启" : "静音",
                              style: TextStyle(
                                color: Colors.white,
                                fontSize: 10,
                              ),
                            )
                          ],
                        ),
                      ),
                    ),
                  ),
                ),
                Expanded(
                  flex: 1,
                  child: Obx(
                    () => GestureAvoidDetector(
                      onTap: () {
                        if (this.controller.isRecording) {
                          this.controller.stopRecording();
                        } else {
                          this.controller.startRecording();
                        }
                      },
                      child: Container(
                        height: 44,
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Icon(
                              CupertinoIcons.video_camera_solid,
                              color: Colors.white,
                            ),
                            Text(
                              this.controller.isRecording ? "停止" : "开始",
                              style: TextStyle(
                                color: Colors.white,
                                fontSize: 10,
                              ),
                            )
                          ],
                        ),
                      ),
                    ),
                  ),
                ),
                Expanded(
                  flex: 1,
                  child: GestureAvoidDetector(
                    onTap: () {
                      this.controller.toggleCamera();
                    },
                    child: Container(
                      height: 44,
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          Icon(
                            CupertinoIcons.camera_rotate_fill,
                            color: Colors.white,
                          ),
                          Text(
                            "切换",
                            style: TextStyle(
                              color: Colors.white,
                              fontSize: 10,
                            ),
                          )
                        ],
                      ),
                    ),
                  ),
                ),
                Expanded(
                  flex: 1,
                  child: Container(
                    height: 44,
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Icon(
                          CupertinoIcons.person_2_fill,
                          color: Colors.white,
                        ),
                        Text(
                          "成员",
                          style: TextStyle(
                            color: Colors.white,
                            fontSize: 10,
                          ),
                        )
                      ],
                    ),
                  ),
                )
              ],
            ),
          ),
        )
      ],
    );
  }

  @override
  TeacherLivingController initController() {
    return TeacherLivingController();
  }

  @override
  Widget buildNavigationBar(BuildContext context) {
    return null;
  }
}
